package com.qys.livesMall.navy.service;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.qys.livesMall.app.user.model.entity.H2AppUserAddress;
import com.qys.livesMall.app.user.service.IH2AppUserAddressService;
import com.qys.livesMall.finance.service.FinanceUserAccountService;
import com.qys.livesMall.navy.task.TaskInter;
import com.qys.livesMall.shop.dao.H2ShopBaseDao;
import com.qys.livesMall.shop.modal.dto.ShopCartDto;
import com.qys.livesMall.shop.modal.dto.shop.order.NavyAddOrder;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.service.*;
import com.qys.livesMall.shop.service.api.impl.ShopOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @menu NavyShopAutoOrderServer
 * @date 2023/09/16 10:34
 */
@Slf4j
@Service
public class NavyShopAutoOrderServer {
    @Autowired
    private H2ShopBaseDao h2ShopBaseService;
    @Autowired
    private ShopGoodsSkuService shopGoodsSkuService;
    @Autowired
    private FinanceUserAccountService financeUserAccountService;

    @Autowired
    private ShopGoodsSkuStocksService shopGoodsSkuStocksService;

    @Autowired
    private ShopGoodsInfoService shopGoodsInfoService;

    @Autowired
    private H2ShopLevelService shopLevelService;

    @Autowired
    private IH2AppUserAddressService userAddressService;

    @Autowired
    private ShopOrderService shopOrderService;

    //正在任务中的店铺id
    private static Set<Long> runShopIds=new HashSet<>();

    @Autowired
    private TaskInter taskInter;

    public void init(){
        //查询所有正常店铺
        log.info("开始加载店铺....");
        //获取店铺
        List<H2ShopBase> shops= h2ShopBaseService.getAllShop();
        if (CollectionUtils.isEmpty(shops)){
            return;
        }
        log.info("店铺加载完成！");
        log.info("开始创建打单任务...共有{}个店铺",shops.size());
        for(H2ShopBase shopBase:shops){
            if (runShopIds.contains(shopBase.getId())){
                continue;
            }
            runTask(shopBase.getId());
            runShopIds.add(shopBase.getId());
        }
        log.info("打单任务创建完成,共有{}个店铺进行任务",runShopIds.size());
    }

    @Async
    public void exc(Long shopId){
        log.info("店铺{} 自动打单...",shopId);
        //取一个有库存的商品sku
        List<ShopGoodsSku> skus = shopGoodsSkuService.getRandSkus(shopId,1);
        if(CollectionUtils.isEmpty(skus)){
            log.info("店铺{} 没有库存了，移除任务...",shopId);
            //没有库存了，移除任务
            runShopIds.remove(shopId);
            return;
        }
        //计算预算
        BigDecimal totalAmount=skus.stream().map(ShopGoodsSku::getPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
        //取一个余额足够的水军
        List<String> userIds=financeUserAccountService.getSufficientAmountUser(totalAmount);
        if (CollectionUtils.isEmpty(userIds)){
            log.error("未找到足够金额:{} 的水军用户",totalAmount);
            runTask(shopId);
            return;
        }
        //构建下单信息
        //获取水军收件地址
        List<Long> userIdsL=userIds.stream().mapToLong(Long::parseLong).boxed().collect(Collectors.toList());
        H2AppUserAddress address=userAddressService.getByUserIds(userIdsL);
        if (address==null){
            log.error("水军》{}，没有默认地址",userIdsL);
            runTask(shopId);
            return;
        }

        for(ShopGoodsSku goodsSku:skus){
            //下单
            NavyAddOrder orderInfo=new NavyAddOrder();
            orderInfo.setUserId(Long.valueOf(address.getUserId()));
            orderInfo.setSkuId(goodsSku.getId());
            orderInfo.setNum(1);
            BeanUtils.copyProperties(address,orderInfo);
            orderInfo.setConsigUser(address.getUserName());
            ShopOrder order=shopOrderService.add(orderInfo);
            //支付
            if (order.getOrderInfo()!=null){
                shopOrderService.pay(order.getOrderInfo().getId());
            }
        }
        runTask(shopId);
    }

    private void runTask(Long shopId){
        //查看店铺可用库存
        Integer num=shopGoodsSkuStocksService.totalStockNumOfUse(shopId);
        if (num<=0){
            //没有库存了，移除任务
            runShopIds.remove(shopId);
            return;
        }
        //查询店铺最后的上架时间
        LocalDateTime upTime=shopGoodsInfoService.getLastUpShelfTime(shopId);
        if (upTime==null){
            upTime=LocalDateTime.now();
        }
        //计算剩余打单天数
        H2ShopBase shop=h2ShopBaseService.getById(shopId);
        H2ShopLevel level=shopLevelService.getById(shop.getShopLevelId());
        int incomeDays=10;
        if (level!=null&&level.getIncomeDays()!=null){
            incomeDays=level.getIncomeDays();
        }
        upTime=upTime.plusDays(incomeDays);
        long hours=LocalDateTimeUtil.between(LocalDateTime.now(),upTime).toHours();
        if (hours<0){
            hours=incomeDays*24;
        }
        if (hours==0){
            hours=1;
        }
        //每小时消耗库存数
        double dayStock = (double)num / (double) hours;

        //下次触发时间间隔（h）
        double interval=1/dayStock;

        long lastTimes=(long) (interval*60*60);

        long fluctuate=(long)(Math.random()*lastTimes);
        //时间波动
        lastTimes=lastTimes/2+fluctuate;
        if (lastTimes>=hours*3600){
            lastTimes=(long)(Math.random()*incomeDays*24*3600);
        }
        //加入时间轮
        Integer time=Integer.parseInt(String.valueOf(lastTimes));
        taskInter.addAutoOrderTask(time,shopId);
        log.info("店铺{}下次打单在{}秒后....",shopId,time);
//        taskInter.addAutoOrderTask(20,shopId);
    }


    public static void main(String[] args) {
        LocalDateTime upTime=LocalDateTime.now().plusDays(-1).plusHours(-1);
        long days=LocalDateTimeUtil.between(LocalDateTime.now(),upTime).toHours();
        System.out.println(days);
        LocalDateTime upTime1=LocalDateTime.now().plusHours(-1);
        upTime1=upTime1.plusDays(1);
        long days1=LocalDateTimeUtil.between(LocalDateTime.now(),upTime1).toHours();
        System.out.println(upTime1+"..."+LocalDateTime.now());
        System.out.println(days1);
        LocalDateTime upTime2=LocalDateTime.now().plusHours(1);
        upTime2=upTime2.plusDays(1);
        long days2=LocalDateTimeUtil.between(LocalDateTime.now(),upTime2).toHours();
        System.out.println(upTime2+"..."+LocalDateTime.now());
        System.out.println(days2);

    }
}

